package demo01;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Test01 {
    private static final int THREAD_COUNT = 10_000;

    public static void main(String[] args) {
        Runnable task = () -> {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        };

        System.out.println("Platform threads:");
        executePlatformThreads(task);

        System.out.println("\nVirtual threads:");
        executeVirtualThreads(task);
    }

    private static void executePlatformThreads(Runnable task) {
        measureTime(() -> {
            try (ExecutorService executor = Executors.newFixedThreadPool(100)) {
                for (int i = 0; i < THREAD_COUNT; i++) {
                    executor.submit(task);
                }
                executor.shutdown();
                executor.awaitTermination(1, TimeUnit.MINUTES);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }

    private static void executeVirtualThreads(Runnable task) {
        measureTime(() -> {
            try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
                for (int i = 0; i < THREAD_COUNT; i++) {
                    executor.submit(task);
                }
                executor.shutdown();
                executor.awaitTermination(1, TimeUnit.MINUTES);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        });
    }

    private static void measureTime(Runnable action) {
        Instant start = Instant.now();
        action.run();
        Instant end = Instant.now();
        Duration duration = Duration.between(start, end);
        System.out.printf("Execution time: %dms%n", duration.toMillis());
    }

}
